-----------------------------------------------------------------------------------------------------------------------------------------
--现在这个文件已经不用了
-----------------------------------------------------------------------------------------------------------------------------------------
targetTable 				= {}
targetType 					= {}
targetSourceTable			= {}
targetSourceTableExra		= {}
includeCFlagTable			= {}

runParseFlag				= 1


-----------------------------------------------------------------------------------------------------------------------------------------
--	展开解析函数开始
-----------------------------------------------------------------------------------------------------------------------------------------
--	例子"e.c  f.c"  --> "e.c","f.c" 
function extraParse(exraString,distTable)
	while 1 < string.len(exraString) do
-- 	跳过空白 
		exraString = skipHeadSpace( exraString )
--	查找出现字符以后后第一个空白
		local headp,headq = string.find(exraString," ")
		if nil == headp or nil == headq then
			break
		end
--	取出左括号 和第一个空白之间的字符串作为目标名字
		local name = string.sub(exraString,1 ,headp)
--	目标名字添加到目标表里
		table.insert(distTable,name)
--	跳过目标名字
		exraString = string.sub(exraString,headq)
	end
--	最后无空格结束的词组
	if 1 < string.len(exraString) then
		table.insert(distTable,exraString)
	end
end
-----------------------------------------------------------------------------------------------------------------------------------------
--	展开解析函数结束
-----------------------------------------------------------------------------------------------------------------------------------------


-----------------------------------------------------------------------------------------------------------------------------------------
--	LLMakeLists.txt解析函数开始
-----------------------------------------------------------------------------------------------------------------------------------------
-- 	跳过字符串开头的空白
--	返回跳过后的字符串
function skipHeadSpace(skipString)
	local headp =1
	while 1 do
		local byte = string.byte(skipString,headp)
--		print(skipString,byte)
		if 32 ~= byte then 
			break
		end
		headp = headp +1
	end
	skipString = string.sub(skipString,headp)
	return skipString
end
--	检查（）括号是否配对
function checkBrackets(commandString)
	local leftp,leftq = string.find(commandString,"%(")
	local rightp,rightq = string.find(commandString,")")
	if nil == leftp or nil == rightp then
		runParseFlag = nil
		return nil
	else
		return 1
	end
end

--	解析共通开始部分
--	add_executable( abc ×××××××)
--	add_library( abc  ××××××)
function parseCommonStart(commandString,distTable)
--	括号配对检查	
	if nil == checkBrackets(commandString) then
		return nil
	end
--	print(commandString)

--	查找左括号( 
	local headp,headq = string.find(commandString,"%(") 		
--	跳过左括号( 
	commandString = string.sub(commandString,headq +1 )
-- 	跳过空白 
	commandString = skipHeadSpace( commandString )
--	print(commandString)

--	查找第一个空白
	headp,headq = string.find(commandString," ")
--	如果没有空白就取右括号前面所有的
	local brp,brq = string.find(commandString,")")
	if headp > brp then
		headp = brp
		headq = brq
	end
--	取出左括号 和第一个空白 (或者 “）” ) 之间的字符串作为目标名字
--	print(headp)
	local first_name = string.sub(commandString,1 ,headp -1)
--	目标名字添加到目标表里
	table.insert(distTable,first_name)
--	跳过目标名字
	commandString = string.sub(commandString,headq)
-- 	跳过空白 
	commandString = skipHeadSpace( commandString )
--	print(commandString)
	return commandString
	
end
--	add_executable解析
--	解析结果放到targetTable，targetType，targetSourceTable
--	返回剩余未解析的字符串
-- 	例子 add_executable( abc  e.c  f.c )
function parseCommand_add_executable( commandString )
--	解析共通开始部分
--	add_executable( abc ×××××××)
	commandString=parseCommonStart(commandString,targetTable)
	if nil == commandString then
		return nil
	end
--	生成目标类型exec
	table.insert(targetType,"exec")
--	查找右括号
	headp,headq = string.find(commandString,")")
--	到右括号为止全为代码（这里不解析变量）
	local source = string.sub(commandString,1 ,headp-1)
--	代码添加到代码表
	table.insert(targetSourceTable,source)

--	跳过已经解析部分
	commandString = string.sub(commandString,headq +1)
--	print(commandString)
	return commandString
end

--	add_library解析
--	解析结果放到targetTable，targetType，targetSourceTable
--	返回剩余未解析的字符串
-- 	例子 add_library( abc  STATIC|SHARED|MODULE e.c  f.c )
function parseCommand_add_library( commandString )
--	解析共通开始部分
--	add_library( abc  ××××××)
	commandString=parseCommonStart(commandString,targetTable)
	if nil == commandString then
		return nil
	end

--	库类型取得
--	当前解析中的库的结尾，在这个范围内查找"STATIC"，"SHARED"，"MODULE"
	local limitp,limitq = string.find(commandString,")")
	local typePos={}
	local typeName={}
--	查找"STATIC"
	headp,headq = string.find(commandString,"STATIC")
	if headq and headq < limitq then
--	记录"STATIC"末尾位置
		table.insert(typePos,headq)
		table.insert(typeName,"STATIC")
	end
--	查找"SHARED"
	headp,headq = string.find(commandString,"SHARED")
	if headq and headq < limitq then
--	记录"SHARED"末尾位置
		table.insert(typePos,headq)
		table.insert(typeName,"SHARED")
	end
--	查找"MODULE"
	headp,headq = string.find(commandString,"MODULE")
	if headq and headq < limitq then
--	记录"MODULE"末尾位置
		table.insert(typePos,headq)
		table.insert(typeName,"MODULE")
	end
--	库类型合并
	if 0 < table.getn(typeName) then 
		local s = table.concat(typeName, "|")
		table.insert(targetType,s)
	else
--	默认为动态库
		table.insert(targetType,"SHARED")
	end
--	最后一个库的出现位置查找
	if 0 < table.getn(typePos) then 
		table.sort(typePos)
		headq = typePos[table.getn(typePos)]
	end
--	跳过所有库类型字符串
	if headq then
		commandString = string.sub(commandString,headq +1)
-- 	skip header space 
		commandString = skipHeadSpace( commandString )
	end
--	print(commandString)

--	到右括号为止全为代码（这里不解析变量）
	headp,headq = string.find(commandString,")")
	local source = string.sub(commandString,1 ,headp-1)
--	代码添加到代码表
	table.insert(targetSourceTable,source)

--	跳过已经解析部分
	commandString = string.sub(commandString,headq +1)
--	print(commandString)
	return commandString
end

--	parseCommand_include_directories解析
--	解析结果放到includeCFlagTable
--	返回剩余未解析的字符串
-- 	例子 include_directories(./include ./include/heads/)
function parseCommand_include_directories( commandString )
--	解析共通开始部分
--	add_executable( abc ×××××××)
	commandString=parseCommonStart(commandString,includeCFlagTable)
	if nil == commandString then
		return nil
	end
--	查找右括号
	headp,headq = string.find(commandString,")")
--	到右括号为止全为头路径（这里不解析变量）
	if headp then
		local include = string.sub(commandString,1 ,headp-1)
	end
--	按空白分拆剩余部分
	if include then
		extraParse(include,includeCFlagTable)
	end
--	代码添加到代码表
--	table.insert(includeCFlagTable,include)
	
--	跳过已经解析部分
	if commandString and headq then
		commandString = string.sub(commandString,headq +1)
	end
--	print(commandString)
	return commandString
end

-----------------------------------------------------------------------------------------------------------------------------------------
--	LLMakeLists.txt解析函数结束
-----------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------------
-- start 
-----------------------------------------------------------------------------------------------------------------------------------------------
print("Begin parse LLMakeLists.txt")
--print("")
--print("")
--print("")
-----------------------------------------------------------------------------------------------------------------------------------------
--	LLMakeLists.txt解析读入
-----------------------------------------------------------------------------------------------------------------------------------------
io.input("LLMakeLists.txt")
-- scan LLMakeLists.txt optain sources & targets and compile rules
LLMakeListsbuff = ""

for line in io.lines() do
-- delete comennt lines   ( begin with #) 
	line = skipHeadSpace(line)
	local headp,headq = string.find(line,"#")
	if 1 ~= headp then
		LLMakeListsbuff = LLMakeListsbuff .. line .. " "
	end
end
--print(LLMakeListsbuff)
-----------------------------------------------------------------------------------------------------------------------------------------
--	LLMakeLists.txt解析主循环
-----------------------------------------------------------------------------------------------------------------------------------------
local makelist= LLMakeListsbuff
while makelist do

--	add_executable 命令
	local exe_retp,exe_retq = string.find(makelist,"add_executable")
	if exe_retp and exe_retq then
		makelist = string.sub(makelist,exe_retq+1)
		makelist = parseCommand_add_executable(makelist)
	end
--	add_library 命令
	local lib_retp,lib_retq = string.find(makelist,"add_library")
	if lib_retp and lib_retq then
		makelist = string.sub(makelist,lib_retq+1)
		makelist = parseCommand_add_library(makelist)
	end
--	include_directories命令
	local inc_retp,inc_retq = string.find(makelist,"include_directories")
	if inc_retp and inc_retq then
		makelist = string.sub(makelist,inc_retq+1)
		makelist = parseCommand_include_directories(makelist)
	end
--	非对应命令的话就停止
	if nil == exe_retp and nil == lib_retp and nil == inc_retq then
		break
	end
end

-----------------------------------------------------------------------------------------------------------------------------------------
--	展开解析主循环开始
-----------------------------------------------------------------------------------------------------------------------------------------
--	代码展开
for i,v in ipairs(targetSourceTable) do 
	extraParse(v,targetSourceTableExra)
end
-----------------------------------------------------------------------------------------------------------------------------------------
--	展开解析主循环结束
-----------------------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------解析结果-------------------------------------------------------------------------
print(table.getn(targetTable))
print (table.concat(targetTable, ","))
print(table.getn(targetType))
print (table.concat(targetType, ","))
print(table.getn(targetSourceTable))
print (table.concat(targetSourceTable, ","))

-----------------------------------------------------------------------------------------------------------------------------------------
--	依赖关系解析
-----------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------
--	编译执行
-----------------------------------------------------------------------------------------------------------------------------------------
--	编译设定
local CC= string.format('%s%s%s',os.getenv("LLVM_GCC_PATH"),"/bin/","llvm-gcc") 
--local BCFLAGS="-emit-llvm-bc"
local BCFLAGS="-emit-llvm -c"
--	为头文件检索路径追加-I
for i,v in ipairs(includeCFlagTable) do
--	print(i,v)
	v= string.format('%s%s',"-I",v)
	includeCFlagTable[i]=v;
end
--	为头文件检索路径参数
local ICFLAGS=table.concat(includeCFlagTable, " ")

--	编译C代码 到 LLVM执行代码
for i,v in ipairs(targetSourceTableExra) do
	local objstr = string.gsub(v,".c",".bc")
--	**********************************************************************************************************
--	"-Dmain=_main" 不明原因，需要_main，要调查
	local cmd_T = {CC,BCFLAGS,ICFLAGS,"-Dmain=_main",v,"-o",objstr}
	local cmd_S=table.concat(cmd_T, " ")
	print(cmd_T[1],cmd_S)
	os.execute(cmd_S)
end

--	链接LLVM代码
local LINK = string.format('%s%s',os.getenv("LLVM_BIN_PATH"),"llvm-link")
for i,v in ipairs(targetTable) do
	local objstr = string.gsub(targetSourceTable[i],".c",".bc")
	local targetbc = string.format('%s%s',v,".bc") 
	local cmd_T = {LINK,"-f","-d","-o",targetbc,objstr}
--	local cmd_T = {LINK,"-o",v,objstr}
	local cmd_S=table.concat(cmd_T, " ")
	print(cmd_T[1],cmd_S)
	os.execute(cmd_S)
end

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--	生成机器代码  可以对应多种机器
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--	优化以及生成汇编代码
local OPT = string.format('%s%s',os.getenv("LLVM_BIN_PATH"),"opt")
local LLC = string.format('%s%s',os.getenv("LLVM_BIN_PATH"),"llc")
for i,v in ipairs(targetTable) do
--	优化    优化级别需要更改的。
	local targetbc = string.format('%s%s',v,".bc")
	local cmd_O_T = {OPT,"-stats","-O3","-f","-o",targetbc,targetbc}
	local cmd_O_S = table.concat(cmd_O_T, " ")
	print(cmd_O_T[1],cmd_O_S)
	os.execute(cmd_O_S)
--	生成汇编代码
	local targetasm = string.format('%s%s',v,".S")
	local cmd_T = {LLC,"-f","-o",targetasm,targetbc}
	local cmd_S=table.concat(cmd_T, " ")
	print(cmd_T[1],cmd_S)
	os.execute(cmd_S)
end


--	使用binutils汇编代码生成机器代码，链接成程序
local AS = string.format('%s%s%s',os.getenv("BINUTILS_NATIVE_PATH"),"/bin/","as")
local LD = string.format('%s%s%s',os.getenv("BINUTILS_NATIVE_PATH"),"/bin/","ld")
local AR = string.format('%s%s%s',os.getenv("BINUTILS_NATIVE_PATH"),"/bin/","ar")
for i,v in ipairs(targetTable) do
--	生成目标文件。
	local targetasm = string.format('%s%s',v,".S")
	local targetobj = string.format('%s%s',v,".o")
	local cmd_O_T = {AS,"-o",targetobj,targetasm}
	local cmd_O_S = table.concat(cmd_O_T, " ")
	print(cmd_O_T[1],cmd_O_S)
	os.execute(cmd_O_S)
--	生成目标程序
	local p,q = string.find(targetType[i],"exec")
	if p then 
		local targetexec = string.format('%s%s',v,".exe")
		local cmd_T = {LD,"-o",targetexec,targetobj}
		local cmd_S=table.concat(cmd_T, " ")
		print(cmd_T[1],cmd_S)
		os.execute(cmd_S)
	end
--	生成静态库
	local p,q = string.find(targetType[i],"STATIC")
	if p then 
		local targetstatic = string.format('%s%s%s',"lib",v,".a")
		local cmd_T = {AR,"r",targetstatic,targetobj}
		local cmd_S=table.concat(cmd_T, " ")
		print(cmd_T[1],cmd_S)
		os.execute(cmd_S)
	end
--	生成动态库
	local p,q = string.find(targetType[i],"SHARED")
	if p then 
		local targetshared = string.format('%s%s%s',"lib",v,".so")
		local cmd_T = {LD,"-shared","-o",targetshared,targetobj}
		local cmd_S=table.concat(cmd_T, " ")
		print(cmd_T[1],cmd_S)
		os.execute(cmd_S)
	end
--	生成模块 现在不对应。
end
